package dnl.util.ui;

import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.JDesktopPane;
import javax.swing.JInternalFrame;

import dnl.util.ui.mdi.TilingStrategy;

public class JDesktopPaneUtils {

	public static AbstractAction[] getBasicDesktopPaneActions(final JDesktopPane desktopPane,
			final TilingStrategy tilingStrategy) {
		AbstractAction tile = new AbstractAction("Tile") {
			@Override
			public void actionPerformed(ActionEvent e) {
				tile2(desktopPane, tilingStrategy);
			}
		};
		AbstractAction cascade = new AbstractAction("Cascade") {
			@Override
			public void actionPerformed(ActionEvent e) {
				cascade(desktopPane);
			}
		};
		return new AbstractAction[] { tile, cascade };
	}

	public static void cascade(JDesktopPane desktopPane, int layer) {
		JInternalFrame[] frames = desktopPane.getAllFramesInLayer(layer);
		if (frames.length == 0)
			return;

		cascade(frames, desktopPane.getBounds(), 24);
	}

	public static void cascade(JDesktopPane desktopPane) {
		JInternalFrame[] frames = desktopPane.getAllFrames();
		if (frames.length == 0)
			return;

		cascade(frames, desktopPane.getBounds(), 24);
	}

	private static void cascade(JInternalFrame[] frames, Rectangle dBounds, int separation) {
		int margin = frames.length * separation + separation;
		int width = dBounds.width - margin;
		int height = dBounds.height - margin;
		for (int i = 0; i < frames.length; i++) {
			frames[i].setBounds(separation + dBounds.x + i * separation, separation + dBounds.y + i
					* separation, width, height);
		}
	}

	@SuppressWarnings("unused")
	private static void tile(JInternalFrame[] frames, Rectangle dBounds) {
		int cols = (int) Math.sqrt(frames.length);
		int rows = (int) (Math.ceil(((double) frames.length) / cols));
		int lastRow = frames.length - cols * (rows - 1);
		int width, height;

		height = dBounds.height / rows;
		if (lastRow == 0) {
			rows--;
		} else {
			if (lastRow < cols) {
				// rows--;
				// width = dBounds.width / lastRow;
				// for (int i = 0; i < lastRow; i++) {
				// frames[cols * rows + i].setBounds(i * width, rows * height,
				// width, height);
				// }
			}
		}

		width = dBounds.width / cols;
		for (int j = 0; j < rows; j++) {
			for (int i = 0; i + j * cols < frames.length; i++) {
				frames[i + j * cols].setBounds(i * width, j * height, width, height);
			}
		}
	}

	private static void tile2(JDesktopPane desktopPane, TilingStrategy strategy) {
		JInternalFrame[] frames = desktopPane.getAllFrames();
		int cols = (int) Math.sqrt(frames.length);
		if (strategy.getPreferredNumberOfColumns() > 0) {
			cols = strategy.getPreferredNumberOfColumns();
		}
		int rows = (int) (Math.ceil(((double) frames.length) / cols));

		Dimension frameSize = findMaximumDimension(frames);
		Dimension newSize = new Dimension((int) frameSize .getWidth() * cols, (int) frameSize
				.getHeight()
				* rows);
		desktopPane.setPreferredSize(newSize);
		// Rectangle dBounds = n
		int lastRow = frames.length - cols * (rows - 1);
		int width, height;

		height = newSize.height / rows;
		if (lastRow == 0) {
			rows--;
		}

		width = newSize.width / cols;
		for (int j = 0; j < rows; j++) {
			for (int i = 0; i + j * cols < frames.length; i++) {
				frames[i + j * cols].setBounds(i * width, j * height, width, height);
			}
		}
	}

	private static Dimension findMaximumDimension(JInternalFrame[] frames) {
		int h = 0, w = 0;
		for (JInternalFrame internalFrame : frames) {
			Dimension d = internalFrame.getPreferredSize();
			if(d.height > h){
				h = d.height;
			}
			if(d.width > w){
				w = d.width;
			}
			
		}
		Dimension frameSize = new Dimension(w, h);
		return frameSize;
	}

}
